package com.heima.wemedia.scan.service.impl;

import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.heima.aliyun.AliyunGreenTemplate;
import com.heima.feign.article.ArticleFeignClient;
import com.heima.file.MinIOTemplate;
import com.heima.model.article.dto.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.entity.WmChannel;
import com.heima.model.wemedia.entity.WmNews;
import com.heima.model.wemedia.entity.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.scan.dao.WmChannelDao;
import com.heima.wemedia.scan.dao.WmNewsDao;
import com.heima.wemedia.scan.dao.WmSensitiveDao;
import com.heima.wemedia.scan.dao.WmUserDao;
import com.heima.wemedia.scan.service.WmNewsAutoScanService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {

    @Resource
    private WmNewsDao wmNewsDao;

    @Resource
    private AliyunGreenTemplate aliyunGreenTemplate;

    @Resource
    private MinIOTemplate minIOTemplate;

    @Resource
    private WmSensitiveDao wmSensitiveDao;

    @Resource
    private WmChannelDao wmChannelDao;

    @Resource
    private WmUserDao wmUserDao;

    @Resource
    private ArticleFeignClient articleFeignClient;


    /**
     * 自媒体文章自动审核
     *
     * @param newsId 自媒体文章id
     */
    @Override
    public void autoScanNews(Long newsId) {
        //1.查询数据库 文章表
        WmNews wmNews = wmNewsDao.queryById(newsId);
        if (wmNews == null) {
            throw new RuntimeException("文章数据不存在");
        }
        //判断文章状态
        if (wmNews.getStatus() != 1) {
            return;
        }

        //2.抽取文章文本内容和图片数据
        Map<String, Object> textAndImages = extractTextAndImages(wmNews);

        //3.内容审核
        String text = textAndImages.get("text").toString();

        //3.1自管理敏感词审核
        Boolean sensitiveScan = handleSensitiveScan(wmNews, text);
        if (!sensitiveScan) {
            return;
        }
        //3.2文本审核
        Boolean textScan = handleTextScan(wmNews, text);
        if (!textScan) {
            return;
        }
        //3.3图片审核
        List<String> images = (List<String>) textAndImages.get("image");
        Boolean ImageScan = handleImageScan(wmNews, images);
        if (!ImageScan) {
            return;
        }

        //4.审核通过后，修改文章状态
        //4.1如果还没到用户设置的发布时间 , 修改文章状态为8即可
        if (wmNews.getPublishTime().getTime() > System.currentTimeMillis()) {
            updateStatus(wmNews, 8, "审核通过");
            return;
        }
        //4.2如果已经到了用户设置的发布时间, 需要修改文章状态为9 , 并且发布文章
        saveApArticle(wmNews);

    }

    /**
     * 审核通过发布文章
     *
     * @param wmNews
     */
    @Override
    public void saveApArticle(WmNews wmNews) {
        //1.封装参数
        ArticleDto articleDto = new ArticleDto();
        BeanUtils.copyProperties(wmNews, articleDto);
        //处理参数 newsId channelName layout authorId authorName
        articleDto.setNewsId(wmNews.getId());
        WmChannel wmChannel = wmChannelDao.queryById(wmNews.getChannelId());
        if (wmChannel != null) {
            articleDto.setChannelName(wmChannel.getName());
        }
        articleDto.setLayout(wmNews.getType());
        articleDto.setAuthorId(wmNews.getUserId());
        WmUser wmUser = wmUserDao.queryById(wmNews.getUserId());
        if (wmUser != null) {
            articleDto.setAuthorName(wmUser.getNickname());
        }

        //2.远程调用feign接口
        ResponseResult result = articleFeignClient.save(articleDto);
        if (result.getCode() == 200) {
            //修改状态为9，
            updateStatus(wmNews, 9, "审核通过，已发布");
        }

    }

    /**
     * 敏感词审核
     *
     * @param wmNews
     * @param text
     * @return
     */
    private Boolean handleSensitiveScan(WmNews wmNews, String text) {
        //1.参数校验
        if (StringUtils.isBlank(text)) {
            return true;
        }

        //2.进行敏感词匹配
        Map<String, Integer> result = SensitiveWordUtil.matchWords(text);
        if (MapUtil.isNotEmpty(result)) {
            updateStatus(wmNews, 2, "文章内容中包含敏感词");
            return false;
        }
        return true;
    }

    /**
     * 图片审核
     *
     * @param wmNews
     * @param images
     * @return
     */
    private Boolean handleImageScan(WmNews wmNews, List<String> images) {
        //参数校验
        if (CollectionUtils.isEmpty(images)) {
            return true;
        }
        //调用阿里云审核
        //去重,并转化为字节数组
        List<byte[]> bytes = images.stream()
                .distinct()
                .map(map -> minIOTemplate.downLoadFile(map))
                .collect(Collectors.toList());
        Map<String, String> imageScan = aliyunGreenTemplate.greenImageScan(bytes);
        String result = imageScan.get("suggestion");
        //审核成功
        if ("pass".equals(result)) {
            return true;
        }
        //审核失败，需要人工审核
        if ("review".equals(result)) {
            //修改文章状态为3
            updateStatus(wmNews, 3, "图片包含不确定信息，需要进一步人工审核");
            return false;
        }
        //审核失败
        if ("block".equals(result)) {
            //修改文章状态为2
            updateStatus(wmNews, 2, "图片包含违规信息，请修改后再提交");
            return false;
        }
        return false;
    }

    /**
     * 文本审核
     *
     * @param wmNews
     * @param text
     * @return
     */
    private Boolean handleTextScan(WmNews wmNews, String text) {
        //参数校验
        if (StringUtils.isBlank(text)) {
            return true;
        }
        //调用阿里云审核
        Map<String, String> textScan = aliyunGreenTemplate.greenTextScan(text);
        String result = textScan.get("suggestion");
        //审核成功
        if ("pass".equals(result)) {
            return true;
        }
        //审核失败，需要人工审核
        if ("review".equals(result)) {
            //修改文章状态为3
            updateStatus(wmNews, 3, "文章内容中包含不确定信息，需要进一步人工审核");
            return false;
        }
        //审核失败
        if ("block".equals(result)) {
            //修改文章状态为2
            updateStatus(wmNews, 2, "文章内容中包含违规信息，请修改后再提交");
            return false;
        }
        return false;
    }

    /**
     * 修改文章状态
     *
     * @param wmNews
     * @param status
     * @param reason
     */
    private void updateStatus(WmNews wmNews, int status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        wmNewsDao.update(wmNews);
    }

    /**
     * 抽取文章文本内容和图片数据
     *
     * @param wmNews
     * @return
     */
    private Map<String, Object> extractTextAndImages(WmNews wmNews) {

        List<Map> content = JSON.parseArray(wmNews.getContent(), Map.class);
        ArrayList<String> images = new ArrayList<>();
        //1.抽取文本 （标题 内容）
        StringBuilder sb = new StringBuilder();
        //1.1标题文本
        sb.append(wmNews.getTitle());
        for (Map map : content) {
            //1.2内容文本数据
            if ("text".equals(map.get("type"))) {
                sb.append(map.get("value")).append(",");
            }

            //2.1内容图片数据
            if ("image".equals(map.get("type"))) {
                images.add(map.get("value").toString());
            }
        }
        //2.2抽取封面图片
        if (StringUtils.isNotBlank(wmNews.getImages())) {
            String[] split = wmNews.getImages().split(",");
            images.addAll(Arrays.asList(split));
        }
        HashMap<String, Object> map = new HashMap<>();
        map.put("text", sb.toString());
        map.put("image", images);
        return map;
    }
}
